module ActiveRecord
  module Acts
    module OAuthConsumer
      def self.included(base)
        base.extend ClassMethods
      end

      module ClassMethods
        def acts_as_oauth_consumer
          return if self.included_modules.include?(ActiveRecord::Acts::OAuthConsumer::ActMethods)

          class_eval do
            include ActiveRecord::Acts::OAuthConsumer::ActMethods
            attr_accessor :callback_url
            
            def self.config
              @config ||= HashWithIndifferentAccess.new(YAML.load(ERB.new((IO.read(File.join(RAILS_ROOT, "config", "#{self.name.tableize}.oauth.yml")))).result))
            end
            
            def self.new_consumer
              # for those config which we need values as symbols..
              %w(scheme http_method).each {|k| config[k] = config[k].to_sym if config[k] }
              OAuth::Consumer.new(config['consumer_key'], config['consumer_secret'], config)
            end
          end
        end
      end
    
      # 
      # Definitely needs re-working here. But will wait
      # for more official "how to do consumer activity"
      # docs from core-lib
      # 
      module ActMethods
        include ::OAuth::RFC3986Encoder
        def query_to_hash(query_string, exclude_keys = [])
          query_string.split('&').inject({}) do |sum, pair|
            key, value = pair.split('=')
            exclude_keys.include?(key.to_s) ? sum : sum.merge({ key => URI.unescape(value.to_s)})
          end
        end
        # 9.1.1.  Normalize Request Parameters
        # http://oauth.googlecode.com/svn/spec/branches/1.0/drafts/5/spec.html#rfc.section.9.1.1
        def hash_to_sortedquery(hash)
          hash.inject([]) do |sum, (key,value)|
            sum + ["#{key}=#{rfc3986_escape(value)}"]
          end.sort.join('&')
        end

        def oauth_request_token
          consumer = self.class.new_consumer
          @request_token = consumer.get_request_token
          self.oauth_token = @request_token.token
          self.oauth_token_secret = @request_token.secret
          @request_token
        end
        
        def oauth_authorization_redirection_url
          authorize_url = @request_token.authorize_url
          uri = URI.parse authorize_url
          uri.query = (uri.query.to_s.split('&') + ["oauth_callback=#{CGI.escape(self.callback_url)}"]).join('&')
          uri.to_s
        rescue
          authorize_url
        end
        
        def oauth_request_access
          @access_token = OAuth::RequestToken.new(self.class.new_consumer, oauth_token, oauth_token_secret).get_access_token
          self.oauth_token = @access_token.token
          self.oauth_token_secret = @access_token.secret
        rescue
          nil
        end
        
        def new_oauth_token
          OAuth::Token.new(oauth_token, oauth_token_secret)
        end

      end
    end
  end
end

ActiveRecord::Base.class_eval { include ActiveRecord::Acts::OAuthConsumer }
